/**
 * 操作日志模块
 */
const createCsvWriter = require('csv-writer').createArrayCsvWriter;
const path = require('path');
const fs = require('fs-extra');
const randomstring = require('randomstring');
const mongoose = require('mongoose');
const cacheUtil = require('../cacheUtil');
const OperationLog = require('./mongo/operation-log');
const ProjectVersion = require('./mongo/project-version');

const operationType = {
  login: '登录',
  create: '新增',
  update: '修改',
  delete: '删除',
  import: '导入',
  export: '导出',
  analyze: '解析',
  execute: '执行',
};

const operationTarget = {
  user: '用户',
  project: '项目',
  version: '版本',
  file: '文件',
  function: '函数',
  testcase: '用例',
  task: '任务',
  defect: '缺陷',
  license: '许可',
  log: '日志',
  template: '模板',
  report: '报告',
  system: '系统',
};
/**
 * 操作结果中文翻译
 * @type {Object}
 */
const operationResultChTran = {
  1: '成功',
  2: '失败',
};

function formatTimestamp(time) {
  const date = new Date(time);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hms = date.toLocaleTimeString('en-US', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });
  return `${year}/${month}/${day} ${hms}`;
}

async function recordOperationLog(data) {
  data.operationTime = (new Date()).getTime();
  return OperationLog.insertMany(data);
}

async function exportOperationLogs(project) {
  const result = {
    cachePath: '',
    reportPath: '',
  };
  result.cachePath = path.join(cacheUtil.getConfigPath('exportDir'), randomstring.generate(16));
  await fs.ensureDir(result.cachePath);
  result.reportPath = path.join(result.cachePath, 'log.csv');
  const logs = await OperationLog.find({ projectId: project._id });
  const csvWriter = createCsvWriter({
    path: result.reportPath,
  });

  const records = [
    ['操作时间', '项目', '版本', '对象', '名称', '操作', '结果', '描述'],
  ];
  const versions = await ProjectVersion.find({ projectId: project._id }, ['_id', 'versionName']).lean();
  const versionsMap = new Map();
  versions.forEach((v) => {
    versionsMap.set(v._id.toString(), v.versionName);
  });
  const deleteVersionIds = new Set();
  logs.forEach((log) => {
    if (log.versionId && !versionsMap.has(log.versionId.toString())) {
      deleteVersionIds.add(log.versionId.toString());
      return Promise.resolve();
    }
    const csvData = [
      formatTimestamp(log.operationTime),
      project.projectName,
      versionsMap.get(log.versionId.toString()),
      operationTarget[log.operationObject],
      log.name,
      operationType[log.operationType],
      operationResultChTran[log.operationResult],
    ];
    const splitLength = 32000;
    for (let i = 0; i < log.operationDesc.length; i += splitLength) {
      csvData.push(log.operationDesc.slice(i, i + splitLength));
    }
    records.push(csvData);
    return Promise.resolve();
  });
  await csvWriter.writeRecords(records);
  if (deleteVersionIds.size > 0) {
    await OperationLog.deleteMany({ versionId: { $in: [...deleteVersionIds].map((id) => mongoose.Types.ObjectId(id)) } });
  }
  return result;
}
/**
 * Export model definition object.
 */
module.exports = {
  exportOperationLogs,
  operationType,
  operationTarget,
  recordOperationLog,
};
